package services

import (
	"context"

	"github.com/samaa/photosalesplus/backend/internal/models"
	"github.com/samaa/photosalesplus/backend/internal/repositories"
)

type ProductPayload struct {
    Title       string
    Type        string
    Description string
    Price       float64
    CoverAssetID *uint
    FreePreviewLimit int
    Images      []ProductImageInput
    IsPublished *bool
}

type ProductImageInput struct {
    AssetID   uint
    SortOrder int
    IsPreview bool
}

type ProductWithStats struct {
	models.Product
	OrdersCount  int64   `json:"orders_count"`
	UnitsSold    int64   `json:"units_sold"`
	TotalRevenue float64 `json:"total_revenue"`
}

type ProductService interface {
	List(ctx context.Context, search string, published *bool, page, pageSize int) ([]ProductWithStats, int64, error)
	Get(ctx context.Context, id uint) (*models.Product, error)
	Create(ctx context.Context, payload ProductPayload) (*models.Product, error)
	Update(ctx context.Context, id uint, payload ProductPayload) (*models.Product, error)
	UpdatePublishStatus(ctx context.Context, id uint, published bool) error
	Delete(ctx context.Context, id uint) error
}

type productService struct {
	repo      repositories.ProductRepository
	orderRepo repositories.OrderRepository
}

func NewProductService(repo repositories.ProductRepository, orderRepo repositories.OrderRepository) ProductService {
	return &productService{
		repo:      repo,
		orderRepo: orderRepo,
	}
}

func (s *productService) List(ctx context.Context, search string, published *bool, page, pageSize int) ([]ProductWithStats, int64, error) {
	if page <= 0 {
		page = 1
	}
	if pageSize <= 0 || pageSize > 100 {
		pageSize = 20
	}

	offset := (page - 1) * pageSize
	products, total, err := s.repo.List(ctx, search, published, pageSize, offset)
	if err != nil {
		return nil, 0, err
	}

	ids := make([]uint, 0, len(products))
	for _, product := range products {
		ids = append(ids, product.ID)
	}

	statsMap, err := s.orderRepo.ProductStatsByIDs(ctx, ids)
	if err != nil {
		return nil, 0, err
	}

	result := make([]ProductWithStats, 0, len(products))
	for _, product := range products {
		stats := statsMap[product.ID]
		result = append(result, ProductWithStats{
			Product:      product,
			OrdersCount:  stats.OrdersCount,
			UnitsSold:    stats.UnitsSold,
			TotalRevenue: stats.TotalRevenue,
		})
	}

	return result, total, nil
}

func (s *productService) Get(ctx context.Context, id uint) (*models.Product, error) {
	return s.repo.GetByID(ctx, id)
}

func (s *productService) Create(ctx context.Context, payload ProductPayload) (*models.Product, error) {
    product := &models.Product{
        Title:       payload.Title,
        Type:        payload.Type,
        Description: payload.Description,
        Price:       payload.Price,
        CoverAssetID: payload.CoverAssetID,
        FreePreviewLimit: payload.FreePreviewLimit,
        IsPublished: true,
    }
	if payload.IsPublished != nil {
		product.IsPublished = *payload.IsPublished
	}

    for _, img := range payload.Images {
        // URL 字段保留为空，依赖 Asset 关联
        product.Images = append(product.Images, models.ProductImage{
            AssetID:   &img.AssetID,
            SortOrder: img.SortOrder,
            IsPreview: img.IsPreview,
        })
    }

	if err := s.repo.Create(ctx, product); err != nil {
		return nil, err
	}
	return s.repo.GetByID(ctx, product.ID)
}

func (s *productService) Update(ctx context.Context, id uint, payload ProductPayload) (*models.Product, error) {
    product, err := s.repo.GetByID(ctx, id)
    if err != nil {
        return nil, err
    }

    product.Title = payload.Title
    product.Type = payload.Type
    product.Description = payload.Description
    product.Price = payload.Price
    product.CoverAssetID = payload.CoverAssetID
    product.FreePreviewLimit = payload.FreePreviewLimit
    if payload.IsPublished != nil {
        product.IsPublished = *payload.IsPublished
    }

    var images []models.ProductImage
    for _, img := range payload.Images {
        images = append(images, models.ProductImage{
            AssetID:   &img.AssetID,
            SortOrder: img.SortOrder,
            IsPreview: img.IsPreview,
        })
    }

	if err := s.repo.Update(ctx, product, images); err != nil {
		return nil, err
	}

	return s.repo.GetByID(ctx, product.ID)
}

func (s *productService) UpdatePublishStatus(ctx context.Context, id uint, published bool) error {
	return s.repo.UpdatePublishStatus(ctx, id, published)
}

func (s *productService) Delete(ctx context.Context, id uint) error {
	return s.repo.Delete(ctx, id)
}
